#多轨热图绘制#



if (!requireNamespace("dendsort", quietly = TRUE)) install.packages("dendsort")
if (!requireNamespace("gridBase", quietly = TRUE)) install.packages("gridBase")


library(ComplexHeatmap)
library(circlize)
library(RColorBrewer)
library(dendextend)
library(dendsort)
library(gridBase)

# https://blog.csdn.net/weixin_54004950/article/details/128225038
# https://www.jianshu.com/p/3a627c02d747 学习参考

##nnBiocManager::install("ComplexHeatmap")

mat <- rbind(
  cbind(matrix(
    rnorm(50*5, mean = 1), nr = 50), 
    matrix(rnorm(50*5, mean = -1), nr = 50)
  ),
  cbind(matrix(
    rnorm(50*5, mean = -1), nr = 50), 
    matrix(rnorm(50*5, mean = 1), nr = 50)
  )
)
rownames(mat) <- paste0("R", 1:100)
colnames(mat) <- paste0("C", 1:10)
mat2 <- mat[sample(100, 100), ]
split <- sample(letters[1:5], 100, replace = TRUE)
split <- factor(split, levels = letters[1:5])

Heatmap(mat, row_split = split)

col_fun <- colorRamp2(c(-2, 0, 2), c("#fc8d59", "#ffffbf", "#91bfdb"))
circos.heatmap(mat, split = split, col = col_fun)
circos.clear()

data=read.table("检查点聚类矩阵3.txt",sep="\t",header=T,check.names=F, row.names = 1)
data <- data[,-7] ##示例数据里多了一列
data <- as.data.frame(data)
#假设有两个热图的矩阵数据（这里仅为一组重复两次以作示范）
###连续性用这个
cir1<-t(scale(t(data)))

cir2<-t(scale(t(data)))

##二分类用这个

cir1 <- data
cir2 <- data
mycol=colorRamp2(c(-2, 0, 2),c("blue","white","red"))#设置legend颜色，范围；可从https://www.58pic.com/peisebiao/网站进行配色

mycol1 = colorRamp2(c(-2, 0, 2), c("#003399", "white", "red"))
#但如果矩阵数据分组，可用split参数来指定分类变量

ann_row = data.frame(pathway=c(rep("pathway1",20),rep("pathway2",20),rep("pathway3",21)))#对行进行注释，用于后续的热图分裂

ann_row2 = data.frame(pathway=c(rep("pathway1",20),rep("pathway2",20),rep("pathway3",21)))#对行进行注释，用于后续的热图分裂

row.names(ann_row) = rownames(cir1)

row.names(ann_row2) = rownames(cir2)

ann_row <- as.matrix(ann_row)#在circlize函数中，需要为matrix

ann_row2 <- as.matrix(ann_row2)

#绘图
circos.clear()

circos.par(gap.after=c(2,2,30)) #circos.par()调整圆环首尾间的距离，数值越大，距离越宽#让分裂的一个口大一点，可以添加行信息

circos.heatmap(cir1,col=mycol,
               
               split=ann_row, #用行注释分裂热图
               
               rownames.col="black",
               cell.border = "black", ##单个单元格边框颜色
               ##na.col = "white", ##设定NA值颜色
               ##cell.lwd = 1, ##边框粗细
               show.sector.labels = T,
               
               #track.height = 0.28, #轨道的高度，数值越大圆环越粗
               
               #rownames.side="inside",控制矩阵行名的方向,与dend.side相同；但注意二者不能在同一侧，必须一内一外
               
               rownames.cex=0.2,#字体大小
               
               rownames.font=1,#字体粗细
               
               bg.border="black", #背景边缘颜色
               
               dend.side="outside",#dend.side：控制行聚类树的方向，inside为显示在圆环内圈，outside为显示在圆环外圈
               
               cluster=FALSE,#cluster=TRUE为对行聚类，cluster=FALSE则不显示聚类
               
               dend.track.height=0.2,#调整行聚类树的高度
               
               dend.callback=function(dend,m,si) { #dend.callback：用于聚类树的回调，当需要对聚类树进行重新排序，或者添加颜色时使用包含的三个参数：dend：当前扇区的树状图；m：当前扇区对应的子矩阵；si：当前扇区的名称
                 
                 color_branches(dend,k=10,col=1:10) #color_branches():修改聚类树颜色#聚类树颜色改为1，即单色/黑色
                 
               }
               
)

circos.heatmap(cir2,
               
               col = mycol1,
               
               split=ann_row2,
               
               rownames.side="inside",
               
               bg.border="red", #背景边缘颜色
               
               rownames.cex=0.3)#加入第二个热图

#添加列名#

#第一个环形列名

circos.track(track.index=get.current.track.index(),panel.fun=function(x,y){
  
  if(CELL_META$sector.numeric.index==3){# the last sector
    
    cn=colnames(cir1)
    
    n=length(cn)
    
    circos.text(rep(CELL_META$cell.xlim[2],n)+convert_x(1,"mm"),#x坐标
                
                (1:n)*0.4+3.6,#调整y坐标,行距+距离中心距(1:n)*1.2+5,
                
                cn,cex=0.6,adj=c(0,1),facing="inside")
    
  }
  
},bg.border=NA)

#第二个环形列名

circos.track(track.index=get.current.track.index(),panel.fun=function(x,y){
  
  if(CELL_META$sector.numeric.index==3){# the last sector
    
    cn=colnames(cir2)
    
    n=length(cn)
    
    circos.text(rep(CELL_META$cell.xlim[2],n)+convert_x(1,"mm"),#x坐标
                
                (1:n)*0.4+1,#调整y坐标,行距+距离中心距(1:n)*1.2+5,
                
                cn,cex=0.6,adj=c(0,1),facing="inside")
    
  }
  
},bg.border=NA)

#添加放置在左侧的图例#

##install.packages("gridBase")

library(gridBase)

lg_Exp1=Legend(title="Exp1",col_fun=mycol,direction = c("vertical"))

lg_Exp2=Legend(title="Exp2",col_fun=mycol1,direction = c("vertical"))

circle_size= unit(0.07,"snpc")

h= dev.size()

lgd_list= packLegend(lg_Exp1,lg_Exp2, max_height = unit(2*h,"inch"))

draw(lgd_list, x = circle_size, just ="left")

circos.clear()

par(mfcol = c(1, 2))
circos.heatmap(
  mat, split = split, col = col_fun, 
  dend.side = "inside"
)
circos.clear()
circos.heatmap(
  mat, split = split, col = col_fun, 
  dend.side = "outside"
)
circos.clear()


par(mfcol = c(1, 2))
circos.heatmap(
  cir1, split = split, col = col_fun, 
  rownames.side = "inside",  dend.side = "outside"
)
circos.clear()
text(0, 0, 'A')
circos.heatmap(
  cir1, split = split, col = col_fun, 
  rownames.side = "outside",  dend.side = "inside"
)
circos.clear()
text(0, 0, 'B')


#############
circos.heatmap(
  cir1, split = split, col = col_fun, 
  rownames.side = "outside",
  rownames.col = 1:nrow(mat) %% 10 + 1,
  rownames.cex = runif(nrow(mat), min = 0.3, max = 1.5),
  rownames.font = 1:nrow(mat) %% 4 + 1
)

##################
par(mfcol = c(1, 2))
circos.heatmap(
  cir1, split = split, col = col_fun, 
  dend.side = "inside"
)
circos.clear()
text(0, 0, "reorder by row means")

circos.heatmap(
  cir1, split = split, col = col_fun, 
  dend.side = "inside", 
  dend.callback = function(dend, m, si) {
    dendsort(dend)
  }
)
circos.clear()
text(0, 0, "reorder by dendsort")

##############

pdf(NULL)
sectors = c("a", "b")
circos.initialize(sectors, xlim = c(0, 1))
circos.track(ylim = c(0, 1))
# x = 0.5, y = 0.5 in sector a and track 1
circlize(0.5, 0.5, sector.index = "a", track.index = 1)

